package org.wu.framework.lazy.orm.database.sql.expand.database.persistence.factory;

import org.wu.framework.lazy.orm.core.config.LazyOperationAttribute;
import org.wu.framework.lazy.orm.core.config.prop.DefaultLazyDataSourceAttribute;
import org.wu.framework.lazy.orm.core.config.prop.LazyDataSourceAttribute;
import org.wu.framework.lazy.orm.database.lambda.dynamic.LazyDynamicDatasourceAdapter;
import org.wu.framework.lazy.orm.database.lambda.dynamic.factory.LazyDynamicAdapterFactory;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.LazySqlOperation;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.cure.CureAdapter;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.cure.CureAdapterFactory;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.method.LazyOperationMethod;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.proxy.LazyOperationProxy;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.translation.adapter.LazyTranslationAdapter;
import org.wu.framework.lazy.orm.database.sql.expand.database.persistence.translation.factory.LazyTranslationAdapterFactory;

import javax.sql.DataSource;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;

/**
 * LazyOperationProxy 代理工厂
 */
public final class LazyOperationProxyFactory {


    /**
     * 创建默认的操作代理对象
     *
     * @param sourceProperties 数据库链接配置
     * @return
     */
    public static LazyOperationProxy createDefaultLazyOperationProxy(LazyDataSourceAttribute sourceProperties) {
        return createDefaultLazyOperationProxy(sourceProperties, null);
    }

    /**
     * 创建默认的操作代理对象
     *
     * @param sourceProperties    数据库链接配置
     * @param lazyOperationAttribute 操作配置
     * @return LazyOperationProxy
     */
    public static LazyOperationProxy createDefaultLazyOperationProxy(LazyDataSourceAttribute sourceProperties,
                                                                     LazyOperationAttribute lazyOperationAttribute) {
        List<LazyOperationMethod> lazyOperationMethods = LazyOperationMethodFactory.createDefaultLazyOperationMethod(lazyOperationAttribute);
        return createLazyOperationProxy(null, sourceProperties, lazyOperationMethods);
    }

    /**
     * 创建默认的操作代理对象
     *
     * @param dataSourceMap    数据源
     * @param lazyOperationAttribute 操作配置
     * @return LazyOperationProxy
     */
    public static LazyOperationProxy createDefaultLazyOperationProxy(Map<String,DataSource> dataSourceMap ,
                                                                     LazyOperationAttribute lazyOperationAttribute) {
        List<LazyOperationMethod> lazyOperationMethods = LazyOperationMethodFactory.createDefaultLazyOperationMethod(lazyOperationAttribute);
        LazyDynamicDatasourceAdapter lazyDynamicAdapter = LazyDynamicAdapterFactory.createLazyDynamicAdapter(dataSourceMap,null);

        CureAdapter cureAdapter = CureAdapterFactory.createCureAdapter(dataSourceMap);
        LazyTranslationAdapter lazyTranslationAdapter = LazyTranslationAdapterFactory.createLazyTranslationAdapter();

        return createLazyOperationProxy(lazyOperationMethods, lazyDynamicAdapter, cureAdapter, lazyTranslationAdapter);
    }


    /**
     * 创建默认的操作代理对象
     *
     * @param sourceProperties     数据库链接配置
     * @param lazyOperationMethods 操作的方法
     * @return
     */
    public static LazyOperationProxy createLazyOperationProxy(LazyDataSourceAttribute sourceProperties,
                                                              List<LazyOperationMethod> lazyOperationMethods) {
        return createLazyOperationProxy(null, sourceProperties, lazyOperationMethods);
    }

    /**
     * 创建默认的操作代理对象
     *
     * @param sourceProperties     数据库链接配置
     * @param lazyOperationMethods 操作的方法
     * @param dataSourceMap        上下文 数据源
     * @return LazyOperationProxy
     */
    public static LazyOperationProxy createLazyOperationProxy(Map<String, DataSource> dataSourceMap,
                                                              LazyDataSourceAttribute sourceProperties,
                                                              List<LazyOperationMethod> lazyOperationMethods
    ) {
        LazyDynamicDatasourceAdapter lazyDynamicAdapter = LazyDynamicAdapterFactory.createLazyDynamicAdapter(dataSourceMap, sourceProperties);

        CureAdapter cureAdapter = CureAdapterFactory.createCureAdapter(sourceProperties);
        LazyTranslationAdapter lazyTranslationAdapter = LazyTranslationAdapterFactory.createLazyTranslationAdapter();

        return createLazyOperationProxy(lazyOperationMethods, lazyDynamicAdapter, cureAdapter, lazyTranslationAdapter);
    }

    /**
     * 创建默认的操作代理对象
     *
     * @param lazyOperationMethods   自定义数据库持久层操作方法
     * @param lazyDynamicAdapter     动态数据源适配器
     * @param cureAdapter            治愈工厂
     * @param lazyTranslationAdapter 数据库orm数据库转换适配器
     * @return LazyOperationProxy
     */
    public static LazyOperationProxy createLazyOperationProxy(List<LazyOperationMethod> lazyOperationMethods,
                                                              LazyDynamicDatasourceAdapter lazyDynamicAdapter,
                                                              CureAdapter cureAdapter,
                                                              LazyTranslationAdapter lazyTranslationAdapter) {
        return new LazyOperationProxy(lazyOperationMethods, lazyDynamicAdapter, cureAdapter, lazyTranslationAdapter);
    }


    /**
     * 创建对象操作
     *
     * @param lazyDataSourceAttribute 数据库链接配置
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(LazyDataSourceAttribute lazyDataSourceAttribute) {
        return createLazyOperation(lazyDataSourceAttribute, null);
    }

    /**
     * 创建对象操作
     *
     * @param lazyDataSourceAttribute 数据库链接配置
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(LazyDataSourceAttribute lazyDataSourceAttribute, LazyOperationAttribute lazyOperationAttribute) {
        LazyOperationProxy defaultLazyOperationProxy = createDefaultLazyOperationProxy(lazyDataSourceAttribute, lazyOperationAttribute);
        return createLazyOperation(defaultLazyOperationProxy);
    }

    /**
     * 创建对象操作
     *
     * @param dataSourceMap 数据源
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(Map<String,DataSource> dataSourceMap, LazyOperationAttribute lazyOperationAttribute) {
        LazyOperationProxy defaultLazyOperationProxy = createDefaultLazyOperationProxy(dataSourceMap, lazyOperationAttribute);
        return createLazyOperation(defaultLazyOperationProxy);
    }

    /**
     * 创建对象操作
     *
     * @param lazyOperationProxy 操作对象代理对象
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(LazyOperationProxy lazyOperationProxy) {
        return (LazySqlOperation) Proxy.newProxyInstance(LazySqlOperation.class.getClassLoader(), new Class[]{LazySqlOperation.class}, lazyOperationProxy);
    }

    /**
     * 创建 LazySqlOperation 对象
     *
     * @param url      数据库地址
     * @param username 用户名称
     * @param password 用户密码
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(String url, String username, String password) {
        LazyDataSourceAttribute lazyDataSourceAttribute = new DefaultLazyDataSourceAttribute();
        lazyDataSourceAttribute.setUrl(url);
        lazyDataSourceAttribute.setUsername(username);
        lazyDataSourceAttribute.setPassword(password);
        return createLazyOperation(lazyDataSourceAttribute);
    }

    /**
     * 创建 LazySqlOperation 对象
     *
     * @param host     数据库IP
     * @param port     数据库端口
     * @param username 用户名称
     * @param password 用户密码
     * @return LazySqlOperation
     */
    public static LazySqlOperation createLazyOperation(String host, int port, String schema, String username, String password) {
        String urlFormat = "jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=utf-8&useSSL=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai";
        String url = String.format(urlFormat, host, port, schema);

        return createLazyOperation(url, username, password);
    }


}
